﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Xml.Linq;

namespace OpticalPowerMeter
{
    /// <summary>
    /// 添加、删除、修改串口组
    /// </summary>
    public class SerialGroupManagement
    {
        private static SerialGroupManagement serialGroup = null;

        private SerialGroupManagement() { }

        /// <summary>
        /// 获取SerialGroupManagement对象，单例模式不能通过构造函数获取对象
        /// </summary>
        /// <returns>SerialGroupManagement对象</returns>
        public static SerialGroupManagement GetInstance()
        {
            if(serialGroup == null)
            {
                serialGroup = new SerialGroupManagement();
            }
            return serialGroup;
        }

        //配置文件保存的完整名称
        private string FileName = System.Environment.CurrentDirectory + "\\Config\\" + "SerialPortsGroup.xml";

        private void InitFile()
        {
            string path = System.Environment.CurrentDirectory + "\\Config";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            #region 如果文件不存在，添加文件
            if (!File.Exists(FileName))
            {
                XDocument xDoc = new XDocument(
                    new XDeclaration("1.0", "UTF-8", "yes"),
                    new XElement("SerialPortsGroup"));
                xDoc.Save(FileName);
            }
            #endregion
        }


        private void AddPortsParam(XElement parentElement, SerialPortParam serialPortParam) {
            string portname = serialPortParam.Portname.Trim();
            string baudrate = serialPortParam.Baudrate.ToString().Trim();
            parentElement.Add(new XElement("SerialPort",new XAttribute("Portname",portname),new XAttribute("Baudrate",baudrate)));
        }


        /// <summary>
        /// 将串口组的信息保存在本地
        /// </summary>
        /// <param name="groupName">串口组的名称</param>
        /// <param name="portParamList">串口参数清单</param>
        public void SaveData(string groupName,List<SerialPortParam> portParamList) {
            InitFile();
            XElement root = XElement.Load(FileName);
            XElement localGroupElement = (from element in root.Elements("SerialGroup")
                                          where element.Attribute("GroupName") != null
                                          && element.Attribute("GroupName").Value.Equals(groupName)
                                          select element
            )?.SingleOrDefault();
            #region 如果本地没有该串口组，直接将配置信息保存
            if (localGroupElement == null)
            {
                localGroupElement = new XElement("SerialGroup",new XAttribute("GroupName",groupName));
                foreach (SerialPortParam serialPortParam in portParamList) {
                    AddPortsParam(localGroupElement,serialPortParam);
                }
                root.Add(localGroupElement);
                root.Save(FileName);
                return;
            }
            #endregion
            #region 如果本地有该串口组，则对比每个串口参数，有差异的刷新
            List<SerialPortParam> localParamList = GetPortParamList(groupName); //获取本地清单
            for(int i = 0; i < localParamList.Count; i++)
            {
                if (!localParamList[i].Equals(portParamList[i]))
                {
                    localGroupElement.RemoveNodes();
                    foreach (SerialPortParam serialPortParam in portParamList)
                    {
                        AddPortsParam(localGroupElement, serialPortParam);
                    }
                    root.Save(FileName);
                    return;
                }
            }
            #endregion
        }


        /// <summary>
        /// 获取串口组清单
        /// </summary>
        /// <returns>串口组清单</returns>
        public List<string> GetPortGroupNameList()
        {
            #region 本地没有相应的配置文件，直接返回空值
            if (!File.Exists(FileName))
            {
                return null;
            }
            #endregion
            XElement root = XElement.Load(FileName);
            IEnumerable<XElement> groupElements = root.Elements("SerialGroup");
            List<string> nameList = new List<string>();
            foreach (XElement groupElement in groupElements) {
                nameList.Add(groupElement.Attribute("GroupName").Value);
            }
            if (nameList.Count == 0)
            {
                return null;
            }
            return nameList;
        }

        /// <summary>
        /// 获取指定串口组的串口清单
        /// </summary>
        /// <param name="groupname">串口组名称</param>
        /// <returns>串口清单</returns>
        public List<SerialPortParam> GetPortParamList(string groupName) {
            #region 本地没有相应的配置文件，直接返回空值
            if (!File.Exists(FileName))
            {
                return null;
            }
            #endregion
            XElement root = XElement.Load(FileName);
            var result = (from element in root.Elements("SerialGroup")
                          where element.Attribute("GroupName") != null
                          && element.Attribute("GroupName").Value.Equals(groupName)
                          select element
            );
            #region 如果没有与要查询的组名相同的组，直接返回空值
            if (result.Count() == 0)
            {
                return null;
            }
            #endregion
            XElement localGroupElement = result.SingleOrDefault();
            IEnumerable<XElement> serialParams = localGroupElement.Elements("SerialPort");  //获取串口配置清单
            #region 获取本地串口配置清单，并返回
            List<SerialPortParam> serialPortList = new List<SerialPortParam>();
            foreach (XElement serialElement in serialParams) {
                string portname = serialElement.Attribute("Portname").Value;
                int baudrate = Convert.ToInt32(serialElement.Attribute("Baudrate").Value);
                SerialPortParam serialPortParam = new SerialPortParam();
                serialPortParam.Portname = portname;
                serialPortParam.Baudrate = baudrate;
                serialPortList.Add(serialPortParam);
            }
            return serialPortList;
            #endregion
        }

        /// <summary>
        /// 删除本地的串口组
        /// </summary>
        /// <param name="groupName">串口组名称</param>
        public void DeleteGroup(string groupName)
        {
            if(groupName == null || groupName == "")
            {
                return;
            }
            #region 本地没有相应的配置文件，直接返回
            if (!File.Exists(FileName))
            {
                return;
            }
            #endregion
            XElement root = XElement.Load(FileName);
            var result = (from element in root.Elements("SerialGroup")
                          where element.Attribute("GroupName") != null
                          && element.Attribute("GroupName").Value.Equals(groupName)
                          select element
            );
            #region 如果没有与要查询的组名相同的组，直接返回
            if (result.Count() == 0)
            {
                return;
            }
            else
            {
                foreach(XElement groupElement in result)
                {
                    groupElement.Remove();
                }
                root.Save(FileName);
            }
            #endregion
        }

    }
}
